/*******************************************************************************
*  file    : gsmmodem.cpp
*  created : 05.08.2013
*  author  : Slyshyk Oleksiy (alexSlyshyk@gmail.com)
*******************************************************************************/

#include "gsmmodem.hpp"
#include "gsmsmsreader.hpp"
#include <qatchat.h>
#include <QTimer>
#include <QDebug>

GsmModem::GsmModem(QObject *parent) :
    QObject(parent),
    initialized_(false),
    initializing_(false),
    serial_baudrate_(9600)
{
    serial_  = new QSerialPort(this);
    timer_   = new QTimer     (this);

    at_chat_ = new QAtChat(serial_, this);
    at_chat_->setDeadTimeout(10000);
}

GsmModem::~GsmModem()
{

}

void GsmModem::init(const QString& name, int baudrate)
{
    serial_baudrate_ = baudrate;
    if(initializing_ == false)
        {
            if(serial_->isOpen())
                serial_->close();
            if(!openSerial(name))
                {
                    initialized_  = false;
                    emit initialized(false);
                    initializing_ = false;
                    return;
                }

            connect(serial_, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(onSerialError(QSerialPort::SerialPortError)) );
            connect(at_chat_, SIGNAL(dead()), this, SLOT(onChatDead())  );

            QTimer::singleShot( 10000,this,SLOT(onModemInitTimeout()) );
            initializing_ = true;
            init_pos_ = 0;
            init_list_<<"AT"
                      <<"AT+CMEE=1" //Ошибки
                      <<"AT+CMGF=0"// Sms PDU
                      <<"AT+CGMI"
                      <<"AT+CGMM"
                      <<"AT+CGMR"
                      <<"AT+CGSN"
                    ;
            at_chat_->chat("AT",this, SLOT(onModemInitResponce(bool,QAtResult)) );
        }
}

void GsmModem::onModemInitResponce(bool ok, const QAtResult& res)
{
    if(ok)
        {
            if(init_list_.at(init_pos_) == "AT+CGMI")
                manufacturer_ = res.content();
            else if(init_list_.at(init_pos_) == "AT+CGMM")
                model_ = res.content();
            else if(init_list_.at(init_pos_) == "AT+CGMR")
                revision_ = res.content();
            else if(init_list_.at(init_pos_) == "AT+CGSN")
                number_ = res.content();
            init_pos_++;
            if(init_pos_ >= init_list_.size())
                {
                    initialized_ = true;
                    emit initialized(true);
                    initializing_ = false;
                }
            else
                {
                    at_chat_->chat(init_list_.at(init_pos_),this, SLOT(onModemInitResponce(bool,QAtResult)) );
                }
        }
    else
        {
            initialized_ = false;
            emit initialized(false);
            initializing_ = false;
            serial_->close();
        }
}

void GsmModem::onModemInitTimeout()
{
    if(initializing_ == true && initialized_ == false)
        {
            initialized_ = false;
            errorString_ = QString(tr("Превышен интервал ожидания ответа от модема."));
            emit initialized(false);
            initializing_ = false;
            serial_->close();
        }
}

void GsmModem::onSerialError(QSerialPort::SerialPortError )
{
    errorString_ = serial_->errorString();
    emit error(PORT_ERROR);
}

void GsmModem::onChatDead()
{
    errorString_ = tr("Primary chat error done.");
    emit error(ATCHAT_ERROR);
}

QString GsmModem::number() const
{
    return number_;
}

QString GsmModem::errorString() const
{
    return errorString_;
}

bool GsmModem::isValid() const
{
    return initialized_;
}

QString GsmModem::revision() const
{
    return revision_;
}

QString GsmModem::model() const
{
    return model_;
}

QString GsmModem::manufacturer() const
{
    return manufacturer_;
}

bool GsmModem::openSerial(const QString& name)
{
    bool res = false;
    errorString_ = "";
    serial_->setPortName(name);
    if (serial_->open(QIODevice::ReadWrite))
        {
            if (       serial_->setBaudRate   (serial_baudrate_)
                    && serial_->setDataBits   (QSerialPort::Data8)
                    && serial_->setParity     (QSerialPort::NoParity)
                    && serial_->setStopBits   (QSerialPort::OneStop)
                    && serial_->setFlowControl(QSerialPort::NoFlowControl)
               )
                {
                    res = true;
                }
            else
                {
                    serial_->close();
                    errorString_ = QString("Can't configure the serial port: %1, "
                                              "error code: %2. Error text: %3")
                            .arg(name).arg(serial_->error()).arg(serial_->errorString());
                }
        }
    else
        {
            errorString_ = QString("Can't opened the serial port: %1, "
                                      "error code: %2. Error text: %3")
                    .arg(name).arg(serial_->error()).arg(serial_->errorString());
        }
    return res;
}

QAtChat*GsmModem::primaryAtChat()
{
    return at_chat_;
}

/*!
    Sends \a command to the modem on the primary AT chat channel.
    If the command fails, the caller will not be notified.

    \sa primaryAtChat(), retryChat()
*/

void GsmModem::chat(const QString &command)
{
    at_chat_->chat( command );
}

/*!
    Sends \a command to the modem on the primary AT chat channel.
    When the command finishes, notify \a slot on \a target.  The slot
    has the signature \c{done(bool,QAtResult&)}.  The boolean parameter
    indicates if the command succeeded or not, and the QAtResult parameter
    contains the full result data.

    The optional \a data parameter can be used to pass extra user data
    that will be made available to the target slot in the QAtResult::userData()
    field.

    \sa primaryAtChat(), retryChat()
*/
void GsmModem::chat(const QString &command, QObject *target, const char *slot, QAtResult::UserData *data)
{
    at_chat_->chat( command, target, slot, data );
}



